#ifndef OPENGLWRAPPER_GLError_H_
#define OPENGLWRAPPER_GLError_H_

#include "OpenGLPrerequisites.h"

namespace OpenGLWrapper
{
	enum class GLError
	{
		GLError_Success,
		GLError_CannotCreateRenderingContext,
		GLError_CannotDeleteRenderingContext,
		GLError_CannotActivateRenderingContext,
		GLError_CannotDeActivateRenderingContext,
		GLError_InvalidRenderingContext,
		GLError_OpenGLNotSupported,
		GLError_RenderContextAlreadyAdded,
		GLError_InvalidIndex,
		GLError_CannotCreateWindow
	};

	//
	// Converts the ErrorCode to string literal
	//
	static std::string ToString(GLError errCode)
	{
		std::string str = "";
		switch (errCode)
		{
		case GLError::GLError_Success:
			str = "Success";
			break;
		case GLError::GLError_CannotCreateRenderingContext:
			str = "Cannot Create Rendering Context";
			break;
		case GLError::GLError_CannotDeleteRenderingContext:
			str = "Cannot Delete Rendering Context";
			break;	
		case GLError::GLError_CannotActivateRenderingContext:
			str = "Cannot Activate Rendering Context";
			break;
		case GLError::GLError_CannotDeActivateRenderingContext:
			str = "Cannot DeActivate Rendering Context";
			break;
		case GLError::GLError_InvalidRenderingContext:
			str = "Invalid Rendering Context";
			break;
		case GLError::GLError_OpenGLNotSupported:
			str = "OpenGL Not Supported";
			break;
		case GLError::GLError_RenderContextAlreadyAdded:
			str = "Render Context Already Added";
			break;
		case GLError::GLError_InvalidIndex:
			str = "Invalid Index";
			break;
		case GLError::GLError_CannotCreateWindow:
			str = "Cannot Create Window";
			break;
		default:
			break;
		}

		return str;
	}

	// The Exception class that descripe the error if the Exceptions is enabled
	class GLException
	{
	public:

		// 
		// if true, all function throw a GLException object
		//
		static bool EnableExceptions;


		//
		// Helpful method to throw exception
		//
		// creates an exception and throw it if the exceptions are enabled, else returns the error code
		//
		static GLError ThrowException(GLError errCode, std::string errString, void* pContext);

	public:

		//
		// Default constructor
		//
		GLException();

		//
		// Name		: Constructor that takes an ErrorCode
		//
		// Params	: - errCode --> the error code associated with the exception
		//
		GLException(GLError errCode);

		//
		// Constructor that takes an ErrorCode and object of user choose
		//
		// Params	: - errCode		--> the error code associated with the exception
		//			  - pContext	--> the data object that is associated with the exception
		//
		GLException(GLError errCode, void* pContext);

		//
		// Constructor that takes an ErrorCode and helpful error message
		//
		// Params	: - errCode		--> the error code associated with the exception
		//			  - errString	--> string message that descripe additional info with the exception
		//
		GLException(GLError errCode, std::string errString);

		//
		// Constructor that takes an ErrorCode and helpful error message and object of user choose
		//
		// Params	: - errCode --> the error code associated with the exception
		//			  - errString	--> string message that descripe additional info with the exception
		//			  - pContext	--> the data object that is associated with the exception
		//
		GLException(GLError errCode, std::string errString, void* pContext);

		//
		// Object destructor
		//
		~GLException();

	public:

		//
		// Returns The Error Code associated with the exception
		//
		GLError GetErrorCode();

		//
		// Returns The string message that descripe additional info with the exception
		//
		std::string GetErrorString();

		//
		// Returns The the data object that is associated with the exception
		//
		void* GetContext();

	protected:

		//
		// The Error Code associated with the exception
		//
		GLError _errCode;

		//
		// The string message that descripe additional info with the exception
		//
		std::string _errString;

		//
		// The the data object that is associated with the exception
		//
		void* _pContext;
	};
}

#endif